import {JPUSH_CONFIG} from "@/config/notification";
import {checkJPushToken, setJPushToken} from "@/services/api/jiguang-push-token";
import * as Device from "expo-device";
import {ResponseCode} from "@/types/api-common";
import {NotificationMessageProps} from "@/types/notification/common";
import JPush from "jpush-react-native";
import NotificationUtils from "@/utils/notification-utils";


interface JPushRegistrationResponse {
    registerID: string;
}

const recentNotifications = new Map();
// 通知去重的时间窗口（毫秒）
const NOTIFICATION_DEDUPE_WINDOW = 6000; // 1分钟

/**
 * 发布通知
 * @param title
 * @param body
 * @param data
 */
async function publishNotification({
                                       title,
                                       body,
                                       data,
                                   }: NotificationMessageProps) {
    // 从data中获取senderId作为去重标识
    const senderId = data?.senderId;

    if (senderId) {
        const now = Date.now();
        const lastNotification = recentNotifications.get(senderId);
        // 检查是否有相同发送者的最近通知
        if (lastNotification) {
            // 如果在去重时间窗口内有相同发送者的通知
            if (now - lastNotification.timestamp < NOTIFICATION_DEDUPE_WINDOW) {
                // 如果内容相同或者非常相似，则跳过此次通知
                if (lastNotification.body === body) {
                    console.log("跳过重复通知:", title, body);
                    return;
                }
            }
        }
        // 更新最近通知记录
        recentNotifications.set(senderId, {
            timestamp: now,
            body: body,
        });

        // 清理过期的通知记录
        for (const [id, notification] of recentNotifications.entries()) {
            if (now - notification.timestamp > NOTIFICATION_DEDUPE_WINDOW) {
                recentNotifications.delete(id);
            }
        }

        // // 使用极光推送的addLocalNotification方法发布本地通知
        JPush.addLocalNotification({
            messageID: (recentNotifications.size).toString(), // 使用纯数字ID，从0开始
            title: title,
            content: body,
            extras: data || {}, // 附加内容
        });
    }
}


/**使用递归方式重试获取推送令牌
 @param maxRetries 最大重试次数
 @param retryDelay 重试延迟时间(毫秒)
 @param currentRetry 当前重试次数
 @returns 极光推送令牌 */
async function getPushTokenWithRetry(
    maxRetries = 3,
    retryDelay = 1000,
    currentRetry = 0
): Promise<string | undefined> {
    try {
        return await new Promise<string>((resolve, reject) => {
            JPush.getRegistrationID(({registerID}: JPushRegistrationResponse) => {
                if (registerID) {
                    console.log("获取到极光推送令牌:", registerID);
                    resolve(registerID);
                } else {
                    reject(new Error("未能获取到极光推送令牌"));
                }
            });
        });
    } catch (error) {
        console.error(`获取极光推送令牌失败: ${error.message || error}`);
        if (currentRetry < maxRetries - 1) {
            console.log(`${retryDelay / 1000}秒后重试获取极光registerID...`);
            await new Promise((resolve) => setTimeout(resolve, retryDelay));
            return getPushTokenWithRetry(maxRetries, retryDelay, currentRetry + 1);
        }
        console.error(`达到最大重试次数(${maxRetries})，获取registerID失败`);
        return null;
    }
}


async function registerForPushNotificationsAsync() {
    if (Device.isDevice) {
        // 请求通知权限
        const b = await NotificationUtils.requestNotificationPermissions();
        if (b) {
            // 开启日志
            JPush.setLoggerEnable(true)
            // 初始化极光推送
            JPush.init(JPUSH_CONFIG);
            JPush.resumePush();
            JPush.addConnectEventListener(async ({connectEnable}) => {
                console.log(connectEnable ? "极光推送连接成功" : "极光推送连接失败");
                if (connectEnable) {
                    const token = NotificationUtils.getToken()
                    if (!token) {
                        const resp = await checkJPushToken();
                        if (resp.data.code === ResponseCode.SUCCESS) {
                            const isTokenSet = resp.data.data;
                            if (!isTokenSet) {
                                try {
                                    const registerId = await getPushTokenWithRetry();
                                    if (!registerId) {
                                        console.error("未能获取到极光推送令牌");
                                        return;
                                    }
                                    const resp = await setJPushToken({registerId});
                                    if (resp.data.code === ResponseCode.SUCCESS) {
                                        console.log("极光推送令牌已成功设置:", registerId);
                                        NotificationUtils.setToken(registerId);
                                    } else {
                                        console.error("设置极光推送令牌失败:", resp.data.message);
                                    }
                                } catch (error) {
                                    console.error("获取极光推送令牌失败:", error);
                                }
                            } else {
                                console.log("极光推送令牌已存在，无需设置");
                            }
                        } else {
                            console.error("检查极光推送令牌失败:", resp.data.message);
                        }
                    }
                }
            });
        }
    }
}


async function unregisterForPushNotifications() {
    // 清除所有本地通知
    JPush.clearAllNotifications();
    // 清除最近通知记录
    recentNotifications.clear();
    // 停止推送服务
    JPush.stopPush();
}

export default {
    publishNotification,
    registerForPushNotificationsAsync,
    unregisterForPushNotifications
}